package com.sayice.icemusic.service.music.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sayice.icemusic.pojo.Music;
import com.sayice.icemusic.service.music.MusicService;
import com.sayice.icemusic.util.encrypt.CloudEncrypt;
import com.sayice.icemusic.util.LyricUtils;
import org.jsoup.Connection;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 网易云音乐服务
 *
 * @author shubing
 */
public class CloudMusicServiceImpl implements MusicService {
    private static final CloudMusicServiceImpl INSTANCE = new CloudMusicServiceImpl();
    
    /**
     * 音乐来源
     */
    private static final String SOURCE_NAME = "网易云音乐";
    
    /**
     * 搜索地址
     */
    private static final String SEARCH_ADDRESS = "https://music.163.com/weapi/cloudsearch/get/web";
    
    /**
     * mp3获取地址
     */
    private static final String MP3_ADDRESS = "https://music.163.com/song/media/outer/url";
    
    /**
     * 歌词获取地址模板
     */
    private static final String LYRIC_ADDRESS_TEMPLATE = "https://music.163.com/api/song/lyric?id=%s&lv=1&kv=1&tv=-1";
    
    private CloudMusicServiceImpl() {
    }
    
    public static CloudMusicServiceImpl getInstance() {
        return INSTANCE;
    }
    
    /**
     * 搜索音乐
     *
     * @param name   音乐名
     * @param sorter 排序方式
     * @return 搜索到的音乐列表
     */
    @Override
    public List<Music> search(String name, String sorter) {
        String reqStr = "{\"total\":\"True\",\"s\":\"" + name + "\",\"offset\":0,\"csrf_token\":\"nothing\",\"limit\":20,\"type\":\"1\",\"n\":1000}";
        List<Music> musicList = new ArrayList<>();
        try {
            Response response = Jsoup.connect(SEARCH_ADDRESS)
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53")
                    .header("Accept", "*/*")
                    .header("Cache-Control", "no-cache")
                    .header("Host", "music.163.com")
                    .header("Accept-Language", "zh-CN,en-US;q=0.7,en;q=0.3")
                    .header("DNT", "1")
                    .header("Pragma", "no-cache")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .data(CloudEncrypt.encrypt(reqStr))
                    .method(Connection.Method.POST)
                    .ignoreContentType(true)
                    .timeout(10000)
                    .execute();
            String body = response.body();
            JSONArray songs = JSON.parseObject(body).getJSONObject("result").getJSONArray("songs");
            for (int i = 0; i < songs.size(); i++) {
                JSONObject jsonObject = songs.getJSONObject(i);
                String musicId = jsonObject.getString("id");
                String musicName = jsonObject.getString("name");
                String mp3Url = mp3UrlOf(musicId);
                String artistName = jsonObject.getJSONArray("ar").getJSONObject(0).getString("name");
                JSONObject albumJsonObject = jsonObject.getJSONObject("al");
                String albumName = albumJsonObject.getString("name");
                String imgUrl = albumJsonObject.getString("picUrl");
                Music music = new Music(musicId, musicName, mp3Url, artistName, albumName, imgUrl, SOURCE_NAME, null);
                musicList.add(music);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return musicList;
    }
    
    /**
     * 获取歌词
     *
     * @param musicId    音乐 id
     * @param sourceName 来源
     * @return 返回歌词信息数组：[[第一句的时间，第一句的内容], [第二句的时间，第二句的内容]……]
     */
    @Override
    public String[][] getLyrics(String musicId, String sourceName) {
        String url = String.format(LYRIC_ADDRESS_TEMPLATE, musicId);
        String lyricsStr;
        try {
            Response response = Jsoup.connect(url)
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53")
                    .ignoreContentType(true)
                    .timeout(10000)
                    .execute();
            String body = response.body();
            lyricsStr = JSON.parseObject(body).getJSONObject("lrc").getString("lyric");
        } catch (Exception e) {
            e.printStackTrace();
            lyricsStr = "[00:00.000]未找到歌词";
        }
        return LyricUtils.parse(lyricsStr);
    }
    
    /**
     * 获取 mp3 地址
     *
     * @param musicId 音乐 id
     * @return mp3地址
     */
    private String mp3UrlOf(String musicId) {
        String url = MP3_ADDRESS + "?id=" + musicId;
        try {
            return Jsoup.connect(url)
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53")
                    .ignoreContentType(true)
                    .timeout(4000)
                    .execute()
                    .url()
                    .toString();
        } catch (Exception e) {
            return url;
        }
    }
}

